#include "plic.h"
#include "mmio.h"  // 内存映射IO操作（需现有项目支持）

// PLIC在QEMU virt平台的物理地址
#define PLIC_BASE 0xc000000
#define PLIC_PRIORITY(id) (PLIC_BASE + 4*(id))
#define PLIC_ENABLE(hart) (PLIC_BASE + 0x2000 + 8*(hart))
#define PLIC_THRESHOLD(hart) (PLIC_BASE + 0x200000 + 0x1000*(hart))
#define PLIC_CLAIM(hart) (PLIC_BASE + 0x200004 + 0x1000*(hart))

// 初始化PLIC（设置默认优先级）
void plic_init(void) {
    // 暂时禁用所有中断（后续通过enable_interrupt开启）
    for (int hart = 0; hart < 1; hart++) {  // 单核心
        mmio_write32(PLIC_ENABLE(hart), 0);
        mmio_write32(PLIC_THRESHOLD(hart), 0);  // 允许所有优先级中断
    }
}

// 设置中断优先级
void plic_set_priority(uint32_t irq, irq_priority_t prio) {
    if (irq == 0) return;  // IRQ0预留
    mmio_write32(PLIC_PRIORITY(irq), prio);
}

// 使能特定中断到指定HART
void plic_enable(uint32_t irq, uint32_t hart) {
    if (irq == 0) return;
    uint32_t mask = mmio_read32(PLIC_ENABLE(hart));
    mask |= (1 << irq);
    mmio_write32(PLIC_ENABLE(hart), mask);
}

// 禁用特定中断
void plic_disable(uint32_t irq, uint32_t hart) {
    if (irq == 0) return;
    uint32_t mask = mmio_read32(PLIC_ENABLE(hart));
    mask &= ~(1 << irq);
    mmio_write32(PLIC_ENABLE(hart), mask);
}

// 读取当前最高优先级中断（CLAIM）
uint32_t plic_claim(uint32_t hart) {
    return mmio_read32(PLIC_CLAIM(hart));
}

// 通知中断处理完成（COMPLETE）
void plic_complete(uint32_t hart, uint32_t irq) {
    mmio_write32(PLIC_CLAIM(hart), irq);
}

void plic_set_threshold(uint32_t hart, uint32_t threshold) {
    mmio_write32(PLIC_THRESHOLD(hart), threshold);
}
